﻿using Adnc.Infra.Mapper.AutoMapper;
using Autofac;
using Autofac.Extras.DynamicProxy;
using Currency.Entity.Shared;
using Currency.Infra.Caching;
using Currency.Infra.Core.Web;
using Currency.Infra.EventBus;
using Currency.Infra.IRepositories;
using Currency.IServices.Shared;
using Currency.IServices.Shared.Interceptors;
using Currency.IServices.Shared.Models;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Currency.Services.Shared
{
    /// <summary>
    /// Services依赖模块注入
    /// </summary>
    public abstract class AutofacServicesModule : Autofac.Module
    {
        private readonly Assembly _appAssemblieToScan;
        private readonly Assembly _entityAssemblieToScan;
        private readonly Assembly _servicesToScan;
        private readonly Assembly _repositoryToScan;
        private readonly IConfigurationSection _redisSection;
        private readonly string _appModuleName;

        /// <summary>
        /// 统一注册WebApi通用模块
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configuration"></param>
        /// <param name="serverInfo"></param>
        /// <param name="completedExecute"></param>
        /// <returns></returns>
        public AutofacServicesModule(Type modelType, IConfiguration configuration, IServiceInfo serviceInfo)
        {
            _appAssemblieToScan = modelType?.Assembly ?? throw new ArgumentNullException(nameof(modelType));
            _entityAssemblieToScan = Assembly.Load(_appAssemblieToScan.FullName.Replace("Services", "Entity"));
            _appModuleName = serviceInfo.ShortName;
            _redisSection = configuration.GetRedisSection();
        }

        protected override void Load(ContainerBuilder builder)
        {
            //注册依赖模块
            this.LoadDepends(builder);

            #region 注册UserContext

            builder.RegisterType<UserContext>()
                        .As<IUserContext, IOperater>()
                        .InstancePerLifetimeScope();

            #endregion

            #region 注册操作日志拦截器

            builder.RegisterType<OperateLogInterceptor>()
                        .AsSelf();
            builder.RegisterType<OperateLogAsyncInterceptor>()
                        .AsSelf();

            #endregion

            #region 注册工作单元拦截器

            builder.RegisterType<UowInterceptor>()
                        .AsSelf();
            builder.RegisterType<UowAsyncInterceptor>()
                        .AsSelf();

            #endregion

            #region 依赖注入Services
            //拦截器
            var interceptors = new List<Type>
            {
                typeof(OperateLogInterceptor)
                ,typeof(UowInterceptor)
            };

            builder.RegisterAssemblyTypes(_appAssemblieToScan)
                       .Where(t => t.IsAssignableTo<IService>() && !t.IsAbstract)
                       .AsImplementedInterfaces()//接口注入
                       .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)//属性注入循环依赖注入方式
                       .InstancePerLifetimeScope()
                       .EnableInterfaceInterceptors()//启用接口拦截
                       .InterceptedBy(interceptors.ToArray());//注册拦截器
            #endregion
        }

        private void LoadDepends(ContainerBuilder builder)
        {
            builder.RegisterModule(new AutofacEventBusModule(_appAssemblieToScan));//注册事件总线
            builder.RegisterModule(new AutoMapperModule(_appAssemblieToScan));//实体与视图映射
            builder.RegisterModule(new AutofacCachingModule(_redisSection));//注册缓存

            var modelType = _entityAssemblieToScan.GetTypes().FirstOrDefault(x => x.IsAssignableTo<AutofacEntityModule>() && !x.IsAbstract);
            builder.RegisterModule(System.Activator.CreateInstance(modelType) as Autofac.Module);

        }
    }
}
